<?php

namespace W3;

!defined('W3_ROOT_DIR') AND exit;

/**
 * 协助收集、分组和显示资产
 *
 * @author edikud
 * @date 2022/10/22
 * @copyright Copyright (c) 2022 W3 (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */

class Asset
{
    protected static $config = [
	   'jsTemplate' => '<script type="text/javascript" src="%s"></script>',
	   'cssTemplate' => '<link rel="stylesheet" href="%s">',
	   'version' => ''
	];

	private static $scripts = [];

	private static $styles = [];

    /**
     * 设置数组项
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public static function config(string $key, string $value)
    {
        self::$config[$key] = $value;
    }

    /**
     * 添加脚本数据队列
     *
     * @param string  $name 脚本名称 【调用的脚本名称，用于区别其它js，因此不能和其它js文件命名相同】
     * @param string $src   JS路径
     * @param [] $deps   依赖关系数组  加载该脚本前需要加载的其它脚本。默认值：[]
     * @param bool $in_footer   默认值：false，放置在区块中。为true时，会出现在区最下方，但必须有_footer()钩子
     */
    public static function addScript(string $name, string $src, $deps = [], $in_footer = false)
    {
		if(is_bool($deps)){
			$in_footer = $deps;
			$deps = [];
		}
		$index = $in_footer ? 'footer' : 'header';
        self::$scripts[$index][$name] = [
		    'src' => $src,
            'deps' => $deps,
			'index' => $index
		];
    }

    /**
     * 删除Script脚本
     *
     * @param string  $name 脚本名称
     * @param bool $in_footer   默认值：false
     */
    public static function removeScript(string $name, bool $in_footer = false)
    {
        unset(self::$scripts[$index][$name]);
    }


    /**
     * 添加脚本数据队列
     *
     * @param string  $name 脚本名称 【调用的脚本名称，用于区别其它CSS，因此不能和其它CSS文件命名相同】
     * @param string $string   CSS路径/CSS字符串
     * @param [] $deps   依赖关系数组  加载该脚本前需要加载的其它脚本。默认值：[]
     */
    public static function addStyle(string $name, string $src, array $deps = [])
    {
        self::$styles[$name] = [
		    'src' => $src,
            'deps' => $deps
		];
    }

    /**
     * 删除脚本
     *
     * @param string  $name 脚本名称
     */
    public static function removeStyle(string $name)
    {
        unset(self::$styles[$name]);
    }

    public static function isSrc(string $src): bool
    {
        return 0 === strpos($src, '/') || 0 === strpos($src, 'http');
    }

	/**
	 * 获取文件或者目录
	 */
	public static function scripts(bool $in_footer = false)
	{
		static $registered, $done = [];

		$index = $in_footer ? 'footer' : 'header';
		if(isset($done[$index])){
			return $done[$index];
		}

		$template = self::$config['jsTemplate'];
		$version = self::$config['version'];
		$scripts = self::$scripts[$index] ?? [];
		$temp = [];

        foreach ($scripts as $name => $script) 
		{
			if($script['deps']){
				foreach ($script['deps'] as $dep)
				{
		            if(isset($scripts[$dep]) && !isset($temp[$dep])) { 
			            $temp[$dep] = $dep;
		            }
				}
			}

		    if(!isset($temp[$name])) { 
			    $temp[$name] = $name;
		    }
		}
		
		'header' == $index && $registered = $temp;
		$string = '';
        foreach ($temp as $name) 
		{
			if('footer' == $index && isset($registered[$name])) {
				continue;
			}	

			$string .= self::isSrc($scripts[$name]['src'])
				? (sprintf($template, $scripts[$name]['src']) . $version . PHP_EOL)
				: '<script type="text/javascript">' .$scripts[$name]['src'] . PHP_EOL . '</script>' . PHP_EOL;
        }

		return $done[$index] = $string;
	}

	public static function styles()
	{
		static $done;

		if(isset($done)){
			return $done;
		}
		
		$template = self::$config['cssTemplate'];
		$version = self::$config['version'];
		$done = '';
		$src = '';
		$temp = [];
		
        foreach (self::$styles as $name => $style) 
		{
			if($style['deps']){
				foreach ($style['deps'] as $dep)
				{
		            if(isset(self::$styles[$dep]) && !isset($temp[$dep])) { 
			            $temp[$dep] = $dep;
						$src = self::$styles[$dep]['src'];
						$done .= self::isSrc($src)
						    ? (sprintf($template, $src) . $version . PHP_EOL)
							: '<style>' . $src . '</style>' . PHP_EOL;
		            }
				}
			}

		    if(!isset($temp[$name])) { 
			    $temp[$name] = $name;
				$src = self::$styles[$name]['src'];
				$done .= self::isSrc($src)
				    ? (sprintf($template, $src) . $version . PHP_EOL)
					: '<style>' . $src . '</style>' . PHP_EOL;
		    }
		}

		return $done;
	}
}